/* MachinePlayer.java */

package player;

import gameboard.GameBoard;

/**
 *  An implementation of an automatic Network player.  Keeps track of moves
 *  made by both players.  Can select a move for itself.
 */
public class MachinePlayer extends Player {
	
	public enum ChipType {BLACK, WHITE, EMPTY};
	private ChipType ownChip, opponentChip;
	public GameBoard gb;
	private int playerColour, searchDepth;

	// Creates a machine player with the given color. Color is either 0 (black)
	// or 1 (white). (White has the first move.)
	public MachinePlayer(int color) {
		playerColour = color;
		gb = new GameBoard(color);
		if (color == 0) {
			ownChip = ChipType.BLACK;
			opponentChip = ChipType.WHITE;

		} else if (color == 1) {
			ownChip = ChipType.WHITE;
			opponentChip = ChipType.BLACK;
		}
	}

	// Creates a machine player with the given color and search depth. Color is
	// either 0 (black) or 1 (white). (White has the first move.)
	public MachinePlayer(int color, int searchDepth) {
		this(color);
		this.searchDepth = searchDepth;
	}

	// Returns a new move by "this" player. Internally records the move (updates
	// the internal game board) as a move by "this" player.
	public Move chooseMove() {
		return new Move();
	}

	// If the Move m is legal, records the move as a move by the opponent
	// (updates the internal game board) and returns true. If the move is
	// illegal, returns false without modifying the internal state of "this"
	// player. This method allows your opponents to inform you of their moves.
	public boolean opponentMove(Move m) {
		// System.out.println("The move in opponentMove is " + m);
		return updateGameBoard(m, opponentChip);
	}

	// If the Move m is legal, records the move as a move by "this" player
	// (updates the internal game board) and returns true. If the move is
	// illegal, returns false without modifying the internal state of "this"
	// player. This method is used to help set up "Network problems" for your
	// player to solve.
	public boolean forceMove(Move m) {
		return updateGameBoard(m, ownChip);
	}
	
	/**
    * updateGameBoard fills in a piece into the gameboard, if the move being made is valid.
    * @param m is the Move
    * @param c is the ChipType
    * @return true if the move is valid, false otherwise
    */
	public boolean updateGameBoard(Move m, ChipType c) {
		// System.out.println("The move in updateGB is " + m);
		// System.out.println("The chiptype in updateGB is " +c);
		if (isValidMove(m, c)) {
			gb.changeChip(m.x1, m.y1, c);
			if (m.moveKind == Move.STEP) {
				gb.changeChip(m.x2, m.y2, ChipType.EMPTY);
			}
			return true;
		}
		return false;
	}

	/**
    *  isValidMove determines whether a Move is valid. A Move is valid when it is not in a  
    *  corner, when it is not in a goal of the opposite colour, and when the square is not already 
    *  occupied.  A player also may not have more than two chips in a connected group,
    *  whether connected orthogonally or diagonally.
    *  
    * @param m is the Move
    * @return true if Move is a valid move, false otherwise
    */
	public boolean isValidMove(Move m, ChipType c) {
		try {
			return gb.getValidity(m.x1, m.y1, c);
		} catch (ArrayIndexOutOfBoundsException e) {
			return false;
		}
	}
	
	public Move[] generateValidMoves(ChipType c){
		Move[] m = new Move[48];
		Move temp;
		int k = 0;
		for(int i = 0; i < 8; i++){
			for(int j = 0; j < 8; j++){
				temp = new Move(i, j);
				if(isValidMove(temp, c)){
					m[k] = temp;
					k++;
				}
			}
		}
		return m;
	}
}